package com.spottydog.virtues;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ViewFlipper;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;

import com.spottydog.virtues.PenMarkLine.OnValuesChangedListener;
import com.spottydog.virtues.quickactions.ActionItem;
import com.spottydog.virtues.quickactions.QuickAction;

public class MainActivity extends Activity {
	
	private static final int DATE_PICKER_DIALOG_ID = 0;
	
	private CompleteDay first;
	private CompleteDay second;
	private CompleteDay third;
	private CompleteDay currentDay;
	
	private VirtueDatabase db;
	private ViewFlipper viewFlipper;
	private GestureDetector gestureDetector;
	@SuppressWarnings("unused")
	private View.OnTouchListener gestureListener;
	private Typeface face;
	
	private Animation slideLeftIn;
	private Animation slideLeftOut;
	private Animation slideRightIn;
	private Animation slideRightOut;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setBackgroundDrawableResource(R.drawable.paper);
        setContentView(R.layout.main);
        
        viewFlipper = (ViewFlipper) findViewById(R.id.view_flipper);
        
    	this.db = new VirtueDatabase(this);
    	this.face = Typeface.createFromAsset(getAssets(), "fonts/BenjaminFranklin.ttf");
    	
    	this.slideLeftIn = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
    	this.slideLeftOut = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
    	this.slideRightIn = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
    	this.slideRightOut = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
    	
    	this.first = new CompleteDay((ViewGroup) findViewById(R.id.first));
    	this.second = new CompleteDay((ViewGroup) findViewById(R.id.second));
    	this.third = new CompleteDay((ViewGroup) findViewById(R.id.third));
    	
    	this.gestureDetector = new GestureDetector(new SwipeGestureDetector());
        this.gestureListener = new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                if (gestureDetector.onTouchEvent(event)) {
                    return true;
                }
                return false;
            }
        };
        
    	fullInit(new Date());
    	
    	Intent showQuote = new Intent(this, QuoteActivity.class);
    	startActivity(showQuote);
    }
    
    private class CompleteDay {
    	CompleteDay(ViewGroup viewGroup) {
    		this.viewGroup = viewGroup;
    	}
    	ViewGroup viewGroup;
    	Date currentDate;
    	List<VirtueDate> virtues;
    }
    
    private void fullInit(Date date) {
    	this.currentDay = this.first;
    	Calendar c = Calendar.getInstance();
    	c.setTime(date);
    	init(this.first, c.getTime());
    	c.add(Calendar.DATE, 1);
    	init(this.second, c.getTime());
    	c.add(Calendar.DATE, -2);
    	init(this.third, c.getTime());
    	viewFlipper.setDisplayedChild(0);
    }
    
    private void init(CompleteDay day, Date forDate) {
    	forDate.setHours(0);
    	forDate.setMinutes(0);
    	forDate.setSeconds(0);
    	day.currentDate = forDate;
    	
    	TextView currentDateView = (TextView) day.viewGroup.findViewById(R.id.date_display);
    	currentDateView.setTypeface(this.face);
    	currentDateView.setText(SimpleDateFormat.getDateInstance(DateFormat.LONG).format(day.currentDate));
    	
    	currentDateView.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {
				showDialog(DATE_PICKER_DIALOG_ID);
				return true;
			}
		});
    	
    	day.virtues = db.getForDate(day.currentDate);
    	
    	ListView virtueList = (ListView) day.viewGroup.findViewById(R.id.virtue_list);
    	VirtueListAdapter adapter = new VirtueListAdapter(this, R.id.virtue_list, day.virtues);
    	virtueList.setAdapter(adapter);
    	virtueList.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> av, View v, int position, long id) {
				PenMarkLine value = (PenMarkLine) v.findViewById(R.id.virtue_value);
				value.addBlot();
			}
		});
    	virtueList.setOnItemLongClickListener(new OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> av, final View v, int position, long id) {
				final QuickAction qa = new QuickAction(v);
				final PenMarkLine value = (PenMarkLine) v.findViewById(R.id.virtue_value);
				
				ActionItem addPlus = new ActionItem();
				addPlus.setIcon(getResources().getDrawable(R.drawable.plus_small));
				addPlus.setTitle("Add plus");
				
				addPlus.setOnClickListener(new OnClickListener() {				
					@Override
					public void onClick(View actionV) {						
						value.addPlus();
						qa.dismiss();
					}
				});
				
				ActionItem addBlot = new ActionItem();
				addBlot.setIcon(getResources().getDrawable(R.drawable.blot_small));
				addBlot.setTitle("Add blot");
				
				addBlot.setOnClickListener(new OnClickListener() {				
					@Override
					public void onClick(View actionV) {						
						value.addBlot();
						qa.dismiss();
					}
				});
				
				ActionItem clear = new ActionItem();
				clear.setIcon(getResources().getDrawable(R.drawable.clear_small));
				clear.setTitle("Clear");
				
				clear.setOnClickListener(new OnClickListener() {		
					@Override
					public void onClick(View v) {
						value.clear();
						qa.dismiss();						
					}
				});
				
				if (!value.isFull()) qa.addActionItem(addPlus);
				if (!value.isFull()) qa.addActionItem(addBlot);
				if (!value.isEmpty()) qa.addActionItem(clear);
				qa.setAnimStyle(QuickAction.ANIM_AUTO);
				qa.show();
				
				return true;
			}
		});
    }
    
    public void goToToday() {
    	jumpToDate(new Date());
    }
    
    public void jumpToDate(Date date) {
    	this.viewFlipper.setInAnimation(null);
    	this.viewFlipper.setOutAnimation(null);
    	fullInit(date);
    }
    
    private void nextDay() {    	
    	CompleteDay next = null;
    	CompleteDay newCurrent = null;
    	
    	if (this.currentDay == this.first) {
    		newCurrent = this.second;
    		next = this.third;
    	} else if (this.currentDay == this.second) {
    		newCurrent = this.third;
    		next = this.first;
    	} else if (this.currentDay == this.third) {
    		newCurrent = this.first;
    		next = this.second;
    	}
    	
    	this.currentDay = newCurrent;
    	   	
    	Calendar c = Calendar.getInstance();
    	c.setTime(this.currentDay.currentDate);
    	c.add(Calendar.DATE, 1);
    	init(next, c.getTime());
    	
    	viewFlipper.setInAnimation(slideLeftIn);
    	viewFlipper.setOutAnimation(slideLeftOut);  	    	
    	viewFlipper.showNext();
    }
    
    private void previousDay() {
    	CompleteDay previous = null;
    	CompleteDay newCurrent = null;
    	
    	if (this.currentDay == this.first) {
    		newCurrent = this.third;
    		previous = this.second;
    	} else if (this.currentDay == this.second) {
    		newCurrent = this.first;
    		previous = this.third;
    	} else if (this.currentDay == this.third){
    		newCurrent = this.second;
    		previous = this.first;
    	}
    	
    	this.currentDay = newCurrent;
    	
    	Calendar c = Calendar.getInstance();
    	c.setTime(this.currentDay.currentDate);
    	c.add(Calendar.DATE, -1);
    	init(previous, c.getTime());
    	
    	viewFlipper.setInAnimation(slideRightIn);
    	viewFlipper.setOutAnimation(slideRightOut);
    	viewFlipper.showPrevious();
    }
    
    @Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main, menu);
		return true;
    }
    
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DATE_PICKER_DIALOG_ID:
			Calendar c = Calendar.getInstance();
			c.setTime(this.currentDay.currentDate);
			return new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {			
				@Override
				public void onDateSet(DatePicker view, int year, int monthOfYear,
						int dayOfMonth) {
					Calendar c = Calendar.getInstance();
					c.set(Calendar.YEAR, year);
					c.set(Calendar.MONTH, monthOfYear);
					c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
					jumpToDate(c.getTime());
				}
			}, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
		}
		return null;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.today:
			goToToday();
			return true;
		case R.id.chart:
			showChart();
			return true;
		case R.id.about:
			showAbout();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	private void showChart() {
		Intent showChart = new Intent(this, ChartActivity.class);
		startActivity(showChart);
	}
	
	private void showAbout() {
		Intent showAbout = new Intent(this, AboutActivity.class);
		startActivity(showAbout);
	}

	private class SwipeGestureDetector extends SimpleOnGestureListener {
    	private static final int SWIPE_MIN_DISTANCE = 50;
    	private static final int SWIPE_THRESHOLD_VELOCITY = 100;
    	
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
				nextDay();
				return true;
			} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
				previousDay();
				return true;
			}		
			return false;
		}

		@Override
		public boolean onDown(MotionEvent e) {
			// This has to be done due to http://code.google.com/p/android/issues/detail?id=8233
			return true;
		}
    }
	
	private class VirtueListAdapter extends ArrayAdapter<VirtueDate> {

		public VirtueListAdapter(Context context, int listViewResourceId, List<VirtueDate> objects) {
			super(context, listViewResourceId, objects);
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {			
			View v = convertView;
			if (v == null) {
				LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				v = vi.inflate(R.layout.virtue_list_item, null);
			}
			
			final VirtueDate vd = getItem(position);
			
			TextView label = (TextView) v.findViewById(R.id.virtue_label);
			TextView description = (TextView) v.findViewById(R.id.virtue_description);
			PenMarkLine value = (PenMarkLine) v.findViewById(R.id.virtue_value);
			
			label.setTypeface(face);
			label.setText(vd.getVirtue().name());
			
			description.setTypeface(face);
			description.setText(VirtueToDescription.getVirtueDescription(vd.getVirtue()));
			
			value.setValuesString(vd.getValues());
			value.setOnValuesChangedListener(new OnValuesChangedListener() {			
				@Override
				public void onValuesChanged(String values, int count) {
					vd.setValues(values);
					vd.setCount(count);
					db.save(vd);
				}
			});
			
			return v;
		}
		
	}

	@Override
	public boolean onTouchEvent(MotionEvent e) {
		return this.gestureDetector.onTouchEvent(e);
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent e){
		super.dispatchTouchEvent(e);
		return this.gestureDetector.onTouchEvent(e);
	}
}